﻿Imports System.Diagnostics.Process

Public Class EZLauncher


    Dim PythonPath As String
    Dim PythonInstalled As Boolean = False
    Dim AppEnginePath As String = "C:\Program Files\Google\google_appengine\dev_appserver.py"
    Dim AppEngineInstalled As Boolean = False
    Dim NeedsSaving As Boolean = False
    Dim ServerRunning As Boolean = False
    Dim DeltaH As Integer
    Dim DeltaW As Integer

    Private Sub UpdateEnabled()
        ' We have an open file
        Dim haveFile As Boolean = (labelFile.Text.Length > 0)
        Dim haveText As Boolean = (editArea.Text.Length > 0)
        Dim haveProject As Boolean = (projectName.Text.Length > 0)
        ' Save As
        bSaveAs.Enabled = haveText
        ' Save
        bSave.Enabled = haveFile And haveText And NeedsSaving
        ' Run Button
        bRun.Enabled = haveProject
        bBrowse.Enabled = haveProject
        bConsole.Enabled = haveProject
        bOpen.Enabled = haveProject
        bNew.Enabled = haveProject
        projectName.Visible = haveProject
    End Sub

    Private Sub Form1_Resize(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Resize
        DoResize()
    End Sub

    Private Sub DoResize()
        DeltaH = 138 ' Me.Size.Height - editArea.Size.Height
        DeltaW = 28 ' Me.Size.Width - editArea.Size.Width
        Dim X As Size = New Size(Me.Size.Width - DeltaW, Me.Size.Height - DeltaH)
        editArea.Size = X
    End Sub

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
          (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As Integer) As Integer


    Private Declare Sub Sleep Lib "kernel32" _
     (ByVal dwMilliseconds As Long)


    Private Sub SetTabStops(ByVal ctlTextBox As TextBox)

        Const EM_SETTABSTOPS As Integer = &HCBS

        ' Set tab stops at character position 4, 8, and 12
        Dim tabs() As Integer = {16, 32, 48, 64, 80, 96, 112, 128, 144}

        SendMessage(ctlTextBox.Handle, EM_SETTABSTOPS, tabs.Length, tabs(0))

    End Sub

    Private Function DoSave(ByVal FileName As String) As Boolean
        Try
            Dim ourText As String = editArea.Text
            My.Computer.FileSystem.WriteAllText(FileName, ourText, False, System.Text.Encoding.ASCII)
            NeedsSaving = False
            labelFile.Text = FileName
            labelPosition.Text = ""
            Return True
        Catch es As Exception
            MessageBox.Show(es.Message)
            Return False
        End Try
    End Function

    Public Function GetPageHTML(ByVal URL As String, _
      Optional ByVal TimeoutSeconds As Integer = 10) _
      As String
        ' Retrieves the HTML from the specified URL,
        ' using a default timeout of 10 seconds
        Dim objRequest As Net.WebRequest
        Dim objResponse As Net.WebResponse
        Dim objStreamReceive As System.IO.Stream
        Dim objEncoding As System.Text.Encoding
        Dim objStreamRead As System.IO.StreamReader

        Try
            ' Setup our Web request
            objRequest = Net.WebRequest.Create(URL)
            objRequest.Timeout = TimeoutSeconds * 1000
            ' Retrieve data from request
            objResponse = objRequest.GetResponse
            objStreamReceive = objResponse.GetResponseStream
            objEncoding = System.Text.Encoding.GetEncoding( _
                "utf-8")
            objStreamRead = New System.IO.StreamReader( _
                objStreamReceive, objEncoding)
            ' Set function return value
            GetPageHTML = objStreamRead.ReadToEnd()
            ' Check if available, then close response
            If Not objResponse Is Nothing Then
                objResponse.Close()
            End If
        Catch
            ' Error occured grabbing data, simply return nothing
            Return ""
        End Try
    End Function

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        SetTabStops(editArea)
        labelFile.Text = ""
        labelPosition.Text = ""
        projectName.Text = ""

        ' Check to see if Python is installed
        If System.IO.File.Exists("C:\Python25\python.exe") Then
            PythonPath = "c:\python25\"
        ElseIf System.IO.File.Exists("C:\Python26\python.exe") Then
            PythonPath = "c:\python26\"
            MsgBox("You appear to have Python 2.6 installed.  You may want to also install a copy of Python 2.5.4 " + _
                   "for use with Google App Engine.  You can install Python 2.5 from http://www.python.org/download/releases/2.5.4/ ")
        Else
            MsgBox("It does not appear that you have Python installed in C:\Python25\ or C:\Python26" + _
                   " - please download and install from www.python.org and then run this program.  " + _
                   " AppEngineLearn suggests Python 2.5.4 even though it is not the most current version of Python.")
            Start("http://www.python.org/download/releases/2.5.4/")
            End
        End If

        ' Check to see if App Engine Run-Time is installed
        If System.IO.File.Exists(AppEnginePath) Then
            AppEngineInstalled = True
        Else
            MsgBox("It does not appear that you have the Google App Engine SDK installed" + _
                   " - please download and install from http://code.google.com/appengine/downloads.html and then run this program.  ")
            Start("http://code.google.com/appengine/downloads.html")
            End
        End If

        Dim html As String = GetPageHTML("http://localhost:8080/", 2)
        If html <> "" Then
            MsgBox("It appears as though there is already a server running on http://localhost:8080/ - you should probably close and restart that server.  The server may be running in a Command Prompt window - to close the server, simply close the Command Prompt window.")
        End If
        UpdateEnabled()
    End Sub

    Private Function ExpandTabs(ByVal inputstring As String) As String
        If inputstring.Length < 1 Then
            Return inputstring
        End If
        Dim thischars As Char() = inputstring.ToCharArray
        Dim thosechars() As Char
        Dim j As Integer = 0
        Dim changed As Boolean
        changed = False
        For i = 0 To thischars.Length - 1
            ReDim Preserve thosechars(0 To j)
            If thischars(i) = vbTab Then
                thosechars(j) = " "
                For k = 1 To 3 - (i Mod 4)
                    j = j + 1
                    ReDim Preserve thosechars(0 To j)
                    thosechars(j) = " "
                    changed = True
                Next
            Else
                thosechars(j) = thischars(i)
            End If
            j = j + 1
        Next
        If Not changed Then
            Return inputstring
        End If

        '  Return the altered string
        Dim retval As String
        retval = thosechars
        Return retval
    End Function

    Private Sub editArea_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles editArea.TextChanged
        ' Debug.Print("YO")
        NeedsSaving = True
        UpdateEnabled()
    End Sub

    Private Sub editArea_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles editArea.KeyUp
        Dim selst = Me.editArea.SelectionStart
        Dim whichline As Integer = Me.editArea.GetLineFromCharIndex(Me.editArea.SelectionStart)
        Dim whichchar As Integer = (selst - Me.editArea.GetFirstCharIndexOfCurrentLine) + 1
        labelPosition.Text = "Line " + (whichline + 1).ToString + ",  Char " + whichchar.ToString
        ' Debug.Print(e.KeyCode)
        If e.KeyCode <> Keys.Tab Then
            Return
        End If

        If Me.editArea.Text.Length < 1 Then
            Return
        End If

        ' Process the current line and expand tabs
        Dim thisline As String = Me.editArea.Lines(whichline)
        Dim newstring = ExpandTabs(thisline)
        If newstring = thisline Then
            Return
        End If

        Dim thelines As String() = Me.editArea.Lines
        thelines(whichline) = newstring
        Me.editArea.Lines = thelines
        Me.editArea.SelectionStart = selst + newstring.Length - thisline.Length

        ' Also Update Row/Column
        selst = Me.editArea.SelectionStart
        whichline = Me.editArea.GetLineFromCharIndex(selst)
        whichchar = (selst - Me.editArea.GetFirstCharIndexOfCurrentLine) + 1
        labelPosition.Text = "Line " + (whichline + 1).ToString + ",  Char " + whichchar.ToString
    End Sub


    Private Sub OpenFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bOpen.Click
        Dim fdlg As OpenFileDialog = New OpenFileDialog()
        fdlg.Title = "C# Corner Open File Dialog"
        fdlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
        If projectName.Text <> "" Then
            fdlg.InitialDirectory = projectName.Text
        End If

        ' fdlg.Filter = "All files (*.*)|*.*|Python files (*.py)|*.py"
        fdlg.FilterIndex = 2
        fdlg.RestoreDirectory = True
        If fdlg.ShowDialog() = DialogResult.OK Then
            labelFile.Text = fdlg.FileName
            Dim readText As String = System.IO.File.ReadAllText(labelFile.Text)
            ' Make sure split() finds the last line
            If readText(readText.Length - 1) <> vbCrLf Then
                readText = readText + vbCrLf
            End If
            ' MsgBox(readText)
            Dim entry = Split(readText, vbCrLf, , vbTextCompare)
            Dim pos As Integer = 0
            Dim expanded As String
            Dim lines(0 To UBound(entry) - 1) As String

            Do While pos < UBound(entry)
                ' MsgBox(entry(pos))
                expanded = ExpandTabs(entry(pos))
                lines(pos) = expanded
                pos = pos + 1
            Loop
            editArea.Lines = lines
            labelPosition.Text = ""
            NeedsSaving = False
        End If
        UpdateEnabled()
    End Sub


    Private Sub saveAs_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bSaveAs.Click
        Try
            Dim fdlg As SaveFileDialog = New SaveFileDialog()
            fdlg.Title = "Open File In Text Editor"
            fdlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
            fdlg.Filter = "All files (*.*)|*.*|Python files (*.py)|*.py"
            fdlg.FilterIndex = 2
            fdlg.RestoreDirectory = True

            If fdlg.ShowDialog() = DialogResult.OK Then
                DoSave(fdlg.FileName)
            End If
        Catch es As Exception
            MessageBox.Show(es.Message)
        End Try
        UpdateEnabled()
    End Sub

    Private Sub doStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bRun.Click
        If projectName.Text.Length < 1 Then
            MsgBox("No Project Found")
            Return
        ElseIf NeedsSaving Then
            If MsgBox("Would you like to save the file " + labelFile.Text, MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
                Return
            End If
            If Not DoSave(labelFile.Text) Then
                Return
            End If
        End If

        Dim savedtext As String = bRun.Text
        bRun.Text = "..."
        bRun.Enabled = False
        Dim html As String = GetPageHTML("http://localhost:8080/", 5)
        If html <> "" Then
            MsgBox("You must close the Command Prompt window that is running your web server before you can open a new one.  If all you are doing is making changes to the files in your application, you do not need to restart the server each time you change a file.  Simply press 'Refresh' in your Browser.")
            bRun.Enabled = True
            bRun.Text = savedtext
            Return
        End If

        UpdateEnabled()
        Dim launch = PythonPath + "python.exe -i """ + AppEnginePath + """ """ + projectName.Text + """"
        ' MsgBox(launch)
        Shell(launch, AppWinStyle.NormalFocus)
        Sleep(3000)
        ' Start("http://localhost:8080")
        ' html = GetPageHTML("http://localhost:8080/", 5)
        ' ServerRunning = html <> ""
        bRun.Enabled = True
        bRun.Text = savedtext
        UpdateEnabled()
    End Sub

    Private Sub NewFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bNew.Click
        editArea.Text = ""
        labelFile.Text = ""
        labelPosition.Text = ""
        UpdateEnabled()
    End Sub

    Private Sub NewProject_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bNewApp.Click
        Try
            Dim fdlg As FolderBrowserDialog = New FolderBrowserDialog()
            fdlg.Description = "Please select or create an empty folder for your new application.  The folder name will also be the name of your application."
            fdlg.RootFolder = Environment.SpecialFolder.DesktopDirectory

            If fdlg.ShowDialog() <> DialogResult.OK Then
                Return
            End If
            ' MsgBox(fdlg.SelectedPath)
            Dim parentPath As String = My.Computer.FileSystem.GetParentPath(fdlg.SelectedPath)
            Dim dirName As String = My.Computer.FileSystem.GetName(fdlg.SelectedPath)
            ' MsgBox(dirName)
            Dim yaml As String = fdlg.SelectedPath + "\app.yaml"
            If Dir(yaml) <> "" Then
                If MsgBox("Do you want to overwrite existing file - " + yaml, MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
                    Return
                End If
            End If
            Dim yamlText As String = "application: " + dirName + vbCrLf + _
                "version: 1" + vbCrLf + "runtime: python" + vbCrLf + "api_version: 1" + _
                vbCrLf + vbCrLf + _
                "handlers:" + vbCrLf + "- url: /.*" + vbCrLf + "  script: index.py" + _
                vbCrLf
            ' MsgBox(yamltext)

            My.Computer.FileSystem.WriteAllText(yaml, yamlText, False, System.Text.Encoding.ASCII)

            Dim index As String = fdlg.SelectedPath + "\index.py"
            If Dir(index) <> "" Then
                If MsgBox("Do you want to overwrite existing file - " + index, MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
                    Return
                End If
            End If

            Dim indexText As String = "print 'Content-Type: text/html'" + vbCrLf + "print ''" + vbCrLf + _
                "print 'Hello, from within your index.py file.'" + vbCrLf + _
                "print '<br/>' " + vbCrLf + _
                "print 'Thanks for installing the <a href=""http://www.appenginelearn.com/welcome"" target=""_new"">www.appenginelearn.com</a> launcher!'"
            My.Computer.FileSystem.WriteAllText(index, indexText, False, System.Text.Encoding.ASCII)
            projectName.Text = fdlg.SelectedPath

        Catch es As Exception
            MessageBox.Show(es.Message)
        End Try
        UpdateEnabled()
    End Sub

    Private Sub OpenProject_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bOpenApp.Click
        projectName.Text = ""
        Dim fdlg As FolderBrowserDialog = New FolderBrowserDialog()
        fdlg.Description = "Please select the folder which contains your Google App Engine application."
        fdlg.RootFolder = Environment.SpecialFolder.DesktopDirectory

        If fdlg.ShowDialog() <> DialogResult.OK Then
            Return
        End If

        If Dir(fdlg.SelectedPath + "\app.yaml") = "" Then
            MsgBox("Folder does not contain an App Engine application (app.yaml) - " + fdlg.SelectedPath)
            Return
        End If
        projectName.Text = fdlg.SelectedPath

        UpdateEnabled()
    End Sub

    Private Sub DoView_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bBrowse.Click
        Start("http://localhost:8080")
    End Sub

    Private Sub Console_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bConsole.Click
        Start("http://localhost:8080/_ah/admin/")
    End Sub

    Private Sub AboutButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AboutButton.Click
        Start("http://www.appenginelearn.com/welcome/")
    End Sub

    Private Sub bSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bSave.Click
        If labelFile.Text.Length < 1 Then
            MsgBox("No File Name Found - Cannot Save")
        Else
            DoSave(labelFile.Text)
        End If
        UpdateEnabled()
    End Sub
End Class
